package com.xxh.dataaccess.service.impl;

import com.xxh.dataaccess.dao.*;
import com.xxh.dataaccess.dao.recall.MovieSimarRecDao;
import com.xxh.dataaccess.dto.MovieDto;
import com.xxh.dataaccess.entity.*;
import com.xxh.dataaccess.page.MongoPageHelper;
import com.xxh.dataaccess.page.PageResult;
import com.xxh.dataaccess.service.MovieService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service("MovieService")
public class MovieServiceImpl implements MovieService {


    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    MongoPageHelper mongoPageHelper;

    @Autowired
    MovieTypeDao movieTypeDao;

    @Autowired
    MovieSimarRecDao movieSimarRecDao;


    @Autowired
    MovieDao movieDao;

    @Autowired
    UserMovieRecDao userMovieRecDao;

    @Autowired
    RateMostMovieDao rateMostMovieDao;

    @Override
    public PageResult<MovieDto> PagingMovies(int cur, int size) {
        Query query = new Query();

        PageResult<Movie> result = mongoPageHelper.pageQuery(query, Movie.class, size, cur);

        long total = result.getTotal();
        Integer pages = result.getPages();
        Integer pageSize = result.getPageSize();
        Integer pageNum = result.getPageNum();
        //查出电影平均分，分数可能随用户增多发生变化，可以分开存放。
        List<MovieDto> dtos = result.getList().stream().map(item -> {
            MovieDto movieDto = new MovieDto();
            BeanUtils.copyProperties(item, movieDto);

            Query q = new Query();
            q.addCriteria(Criteria.where("mid").is(movieDto.getMid()));
            MovieAvgScore score = mongoTemplate.findOne(q, MovieAvgScore.class);
            if (null == score) {
                movieDto.setScore(0.0);
            } else {
                movieDto.setScore(score.getAvgscore());
            }

            return movieDto;
        }).collect(Collectors.toList());


        PageResult<MovieDto> moiveResult = new PageResult<>();
        moiveResult.setList(dtos);
        moiveResult.setTotal(total);
        moiveResult.setPageSize(pageSize);
        moiveResult.setPages(pages);
        moiveResult.setPageNum(pageNum);
        return moiveResult;

    }

    @Override
    public List<String> getAllMovieTypes() {

        List<movieType> all = movieTypeDao.findAll();
        List<String> list = all.stream().map(item -> {
            return item.getValue();
        }).collect(Collectors.toList());
        return list;
    }


    @Override
    public MovieDto getMovieByMid(Integer mid) {
        MovieDto movieDto = new MovieDto();
        Query q = new Query();
        q.addCriteria(Criteria.where("mid").is(mid));
        Movie movie = mongoTemplate.findOne(q, Movie.class);
        BeanUtils.copyProperties(movie, movieDto);
        MovieAvgScore score = mongoTemplate.findOne(q, MovieAvgScore.class);
        if (null == score) {
            movieDto.setScore(0.0);
        } else {
            movieDto.setScore(score.getAvgscore());
        }
        return movieDto;
    }


    @Override
    public List<Movie> getSimilarMovie(Integer mid) {

        MovieSimarRec rec = movieSimarRecDao.findByMid(mid);
        List<Integer> mids = rec.getRec().stream().map(i -> {
            return i.getMid();
        }).collect(Collectors.toList());
        List<Movie> movies = movieDao.findMovieByMidIn(mids);
        return movies;
    }

    @Override
    public List<Movie> getMoviesByMids(List<Integer> mids) {
        List<Movie> movies = movieDao.findMovieByMidIn(mids);
        return movies;
    }

    @Override
    public List<Movie> getMovieByUid(Integer uid) {
        UserMovieRec rec = userMovieRecDao.findByUid(uid);
        if (null != rec) {
            List<Integer> mids = rec.getRec().stream().map(i -> {
                return i.getMid();
            }).collect(Collectors.toList());
            //将召回集的视频随机打乱，取出20条
            Collections.shuffle(mids);
            List<Movie> movies = movieDao.findMovieByMidIn(mids.subList(0, 20));
            return movies;
        } else {
            //用户没有进行过评分操作,返回空值。
            List<Movie> movies = new ArrayList<>();
            return movies;
        }
    }

    @Override
    public List<Movie> getRankList() {

        List<RateMostMovies> all = rateMostMovieDao.findAll();
        List<Integer> mids = all.stream()
                .sorted(Comparator.comparing(RateMostMovies::getMid).reversed())
                .map(item -> {
                    return Math.toIntExact(item.getMid());
                }).collect(Collectors.toList());

        List<Movie> movies = movieDao.findMovieByMidIn(mids);
        return movies;
    }


}
